#pragma once

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <signal.h>
#include "Log.hpp"
#include "ThreadPool.hpp"
#include "Task.hpp"
// #include "Daemon.hpp"

const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";
const int backlog = 10; // 但是一般不要设置的太大

extern Log lg;

enum
{
    UsageError,
    SocketError,
    BindError,
    ListenError
};
class TcpServer;
class ThreadData
{
public:
   ThreadData(int fd, const std::string &ip, const uint16_t &p, TcpServer* t): sockfd(fd), clientip(ip), clientport(p), tsvr(t)
    {}
public:
    int sockfd;
    std::string clientip;
    uint16_t clientport;
    TcpServer* tsvr;
};

class TcpServer
{
public:
    TcpServer(const uint16_t &port, const std::string ip = defaultip) : _listensock(defaultfd), _port(port), _ip(ip)
    {}

    void InitServer()
    {
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock < 0)
        {
            lg(Fatal, "create socket, errno: %d, errstring: %s", errno, strerror(errno));
            exit(SocketError);
        }
        lg(Info, "create socket success, listensock_: %d", _listensock);

        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));//对结构体初始化为0
        local.sin_family = AF_INET;//协议家族IPV4
        local.sin_port = htons(_port);//端口号主机转网络
        inet_aton(_ip.c_str(), &(local.sin_addr));//ip字符串转4字节

        if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)//绑定
        {
            lg(Fatal, "bind error, errno: %d, errstring: %s", errno, strerror(errno));
            exit(BindError);
        }
        lg(Info, "bind socket success, listensock_: %d", _listensock);
        // TCP是面向连接的，
        if (listen(_listensock, backlog) < 0)//监听
        {
            lg(Fatal, "listen error, errno: %d, errstring: %s", errno, strerror(errno));
            exit(ListenError);
        }
        lg(Info, "listen socket success, listensock_: %d", _listensock);
    }

    // static void* Routine(void* args)
    // {
    //     pthread_detach(pthread_self());
    //     ThreadData* td = static_cast<ThreadData*>(args);
    //     td->tsvr->Service(td->sockfd, td->clientip, td->clientport);
    //     delete td;
    //     return nullptr;  
    // }

    void Start()
    {
        //先启动线程池
        ThreadPool<Task>::GetInstance()->Start();
        //signal(SIGCHLD,SIG_IGN);对子进程信号进行忽略处理
        lg(Info, "tcpserver is running...");
        for (;;)
        {
            // 获取连接
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(_listensock, (struct sockaddr *)&client, &len);//接收来自客户端的连接
            if (sockfd < 0)
            {
                lg(Warning, "accept error, errno: %d, errstring: %s", errno, strerror(errno));
                continue;
            }
            uint16_t clientport = ntohs(client.sin_port);//对客户端的端口号网络转主机
            char clientip[32];
            inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip)); // 协议家族，要转的地址，转到ipstr缓冲区

            // 2.根据新连接来进行通信
            lg(Info, "get a new link..., sockfd: %d, client is :%s, client port: %d", sockfd, clientip, clientport);

            // version1 -- 单进程版
            // Service(sockfd, clientip, clientport);
            // close(sockfd);

            //version2 -- 多进程版
            // pid_t id = fork();
            // if(id == 0)
            // {
            //     //child
            //     close(_listensock);
            //     if(fork() > 0) exit(0);//创建孙子进程，让子进程退出，这样父进程就回收子进程了，孙子进程在执行
            //     Service(sockfd, clientip, clientport);
            //     close(sockfd);
            //     exit(0);
            // }
            // // father
            // close(sockfd);
            // pid_t rid = waitpid(id,nullptr,0);
            // (void)rid;

            //version3 -- 多线程版本 每来一个客户端就创建一个线程，客户端越多，线程越多，并且来客户端才创建线程，慢了
            // ThreadData* td = new ThreadData(sockfd,clientip,clientport,this);
            // pthread_t tid;
            // pthread_create(&tid,nullptr,Routine,td);

            //version4 -- 线程池版本
            Task t(sockfd,clientip,clientport);
            ThreadPool<Task>::GetInstance()->Push(t);
        }
    }

    // void Service(int sockfd, const std::string &clientip, const uint16_t &clientport)
    // {
    //     while (true)
    //     {
    //         char buffer[4096];
    //         ssize_t n = read(sockfd, buffer, sizeof(buffer));
    //         if (n > 0)
    //         {
    //             buffer[n] = 0;   
    //             std::cout << "client say@: " << buffer <<std::endl;
    //             std::string echo_string = "Tcpserver get a message for client: ";
    //             echo_string += buffer;
    //             write(sockfd, echo_string.c_str(), echo_string.size());
    //         }
    //         else if(n == 0)
    //         {
    //             lg(Info,"%s:%d quit, server close sockfd:%d",clientip.c_str(),clientport,sockfd);
    //             break;
    //         }
    //         else
    //         {
    //             lg(Warning,"%s:%d read error, close sockfd:%d",clientip.c_str(),clientport,sockfd);
    //             break;
    //         }
    //     }
    // }

    ~TcpServer() {}

private:
    int _listensock;
    uint16_t _port;
    std::string _ip;
};
